<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    <title>划词评论 - Vditor</title>
    <meta name="robots" content="index,follow,archive">
    <meta name="description"
          content="Vditor - 易于使用的 Markdown 编辑器，为适配不同的应用场景而生。它使用 TypeScript 实现，支持原生 JavaScript、Vue、React、Angular，提供桌面版。"/>
    <meta name="copyright" content="B3log"/>
    <link rel="canonical" href="https://b3log.org/vditor/demo/advanced-upload.html">
    <link rel="apple-touch-icon" href="https://b3log.org/images/brand/vditor-128.png">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta http-equiv="Window-target" content="_top"/>
    <link rel="icon" type="image/png" href="https://b3log.org/images/brand/vditor-128.png"/>
    <link rel="shortcut icon" type="image/x-icon" href="https://b3log.org/images/brand/vditor-512.png"/>
    <link type="text/css" rel="stylesheet" href="https://b3log.org/css/base.css" charset="utf-8"/>

    <meta property="og:locale" content="zh_CN"/>
    <meta property="og:title" content="划词评论 - Vditor"/>
    <meta property="og:description"
          content="Vditor - 易于使用的 Markdown 编辑器，为适配不同的应用场景而生。它使用 TypeScript 实现，支持原生 JavaScript、Vue、React、Angular，提供桌面版。"/>
    <meta property="og:image" content="https://b3log.org/images/brand/vditor-128.png"/>
    <meta property="og:url" content="https://b3log.org/vditor"/>
    <meta property="og:site_name" content="B3log"/>
    <meta name="twitter:card" content="summary_large_image"/>
    <meta name="twitter:description"
          content="Vditor - 易于使用的 Markdown 编辑器，为适配不同的应用场景而生。它使用 TypeScript 实现，支持原生 JavaScript、Vue、React、Angular，提供桌面版。"/>
    <meta name="twitter:title" content="划词评论 - Vditor"/>
    <meta name="twitter:image" content="https://b3log.org/images/brand/vditor-128.png"/>
    <meta name="twitter:url" content="https://b3log.org/vditor"/>
    <meta name="twitter:site" content="@b3logos"/>
    <meta name="twitter:creator" content="@b3logos"/>
    <script src="https://b3log.org/vditor/vditor.js" defer></script>
    <style>
        .header {
            background-color: #fff;
            box-shadow: rgba(0, 0, 0, 0.05) 0 1px 7px;
            border-bottom: 1px solid #e1e4e8;
        }

        #comments {
            overflow: auto;
            position: relative;
            flex-shrink: 0;
            width: 260px;
        }

        #comments .vcomment__input {
            padding: 5px 10px;
        }

        #comments > div {
            position: absolute;
        }

        #comments .fn-flex > button {
            margin-left: 10px;
            white-space: nowrap;
        }
    </style>
</head>
<body>
<div class="header fn-clear">
    <a class="header-logo" href="https://b3log.org/vditor">
        <img src="https://b3log.org/images/brand/vditor-128.png">
        <h1>Vditor</h1>
    </a>
    <div class="fn-clear">
        <a class="header-a" href="https://ld246.com/tag/vditor" target="_blank">社区</a>
        <a class="header-a header-red" target="_blank" href="https://ld246.com/article/1549638745630">API</a>
        <a class="header-a header-green current" href="index.html">Demo</a>
        <a class="header-a header-yellow" href="https://ld246.com/sponsor" target="_blank">成为赞助者</a>
    </div>
</div>
<div class="wrapper">
    <div class="fn-50"></div>
    相关 <a href="https://ld246.com/article/1549638745630" target="_blank">API</a>：
    options.comment，Vditor.getCommentIds，Vditor.hlCommentIds，Vditor.unHlCommentIds，Vditor.removeCommentIds<br>
    ⚠️ 注意事项：
    <ul style="margin-left: 30px">
        <li>目前仅支持 wysiwyg 模式</li>
    </ul>
    <div class="fn-50"></div>
    <div class="fn-flex">
        <div id="vditor" style="flex: 1"></div>
        <div id="comments" style="margin-left: 20px"></div>
    </div>
    <div id="vditorDemoCode" class="vditor-reset">
        <pre><code class="javascript">
    const bindCommentEvent = (cmtElement) => {
      const inputElement = cmtElement.querySelector('input')
      const id = cmtElement.getAttribute('data-id')
      inputElement.addEventListener('blur', () => {
        if (inputElement.value.trim() === '') {
          vditor.removeCommentIds([id])
          cmtElement.remove()
        }
      })
      cmtElement.querySelector('button').addEventListener('click', () => {
        vditor.removeCommentIds([id])
        removeComment(cmtElement, id)
      })

      cmtElement.addEventListener('mouseover', () => {
        vditor.hlCommentIds([id])
      })

      cmtElement.addEventListener('mouseout', () => {
        vditor.unHlCommentIds([id])
      })
    }

    const removeComment = (cmtElement, id) => {
      cmtElement.remove()

      let cmts = localStorage.getItem('cmts')
      if (!cmts) {
        return
      } else {
        cmts = JSON.parse(cmts)
      }
      cmts.find((item, index) => {
        if (item.id === id) {
          cmts.splice(index, 1)
          return true
        }
      })
      localStorage.setItem('cmts', JSON.stringify(cmts))
    }

    const renderComments = (ids) => {
      let cmts = localStorage.getItem('cmts')
      if (!cmts) {
        localStorage.setItem('cmts', '[]')
        cmts = []
      } else {
        cmts = JSON.parse(cmts)
      }

      ids.forEach(id => {
        let text = ''
        cmts.find((item) => {
          if (item.id === id) {
            text = item.text
            return true
          }
        })

        const cmtElement = document.createElement('div')
        cmtElement.setAttribute('data-id', id)
        cmtElement.innerHTML = `&lt;div>
${text}&lt;br>
&lt;button>删除&lt;/button>&lt;br>
&lt;input class="vcomment__input">
&lt;/div>`
        cmtElement.value = text
        document.getElementById('comments').
          insertAdjacentElement('beforeend', cmtElement)
        bindCommentEvent(cmtElement)
      })
    }

    vditor = new Vditor('vditor', {
      mode: 'wysiwyg',
      height: 360,
      cache: false,
      value: '选中文字后即可进行评论',
      comment: {
        enable: true,
        add (id, text) {
          const cmtElement = document.createElement('div')
          cmtElement.setAttribute('data-id', id)
          cmtElement.innerHTML = `&lt;div>
${text}&lt;br>
&lt;button>删除&lt;/button>&lt;br>
&lt;input class="vcomment__input">
&lt;/div>`
          cmtElement.value = text
          document.getElementById('comments').
            insertAdjacentElement('beforeend', cmtElement)
          bindCommentEvent(cmtElement)
          cmtElement.querySelector('input').focus()
          let cmts = localStorage.getItem('cmts')
          if (!cmts) {
            localStorage.setItem('cmts', '[]')
            cmts = []
          } else {
            cmts = JSON.parse(cmts)
          }
          cmts.push({id, text})
          localStorage.setItem('cmts', JSON.stringify(cmts))
        },
        remove (ids) {
          ids.forEach((id) => {
            removeComment(document.querySelector(`#comments div[data-id="${id}"]`),
              id)
          })
        },
      },
      after () {
        renderComments(vditor.getCommentIds())
      },
    })
        </code></pre>
    </div>
    <div class="fn-100"></div>
    <div class="fn-clear">
        <h2 class="fn-left">参与讨论</h2>
        <span class="fn-right" style="line-height: 36px" id="commentCnt"></span>
    </div>
    <div class="fn-50"></div>
    <div id="vditorComments"></div>
    <div class="fn-100"></div>
</div>
<!-- end main -->

<div class="footer">
    <div class="wrapper fn-clear">
        <a href="https://b3log.org">首页</a> &nbsp; &nbsp;
        <a href="https://ld246.com" target="_blank">社区</a> &nbsp; &nbsp;
        <a href="https://b3log.org/brand-marking.html">品牌标识</a> &nbsp; &nbsp;
        <a href="https://ld246.com/sponsor" target="_blank">成为赞助者</a>
        <div class="fn-right">
            <a href="https://beian.miit.gov.cn/" target="_blank">滇ICP备14007358号-1</a> &nbsp; &nbsp;
            © 2023 云南链滴科技有限公司
        </div>
    </div>
</div>
<script>
  let vditor
  vditorScript = () => {
    const bindCommentEvent = (cmtElement) => {
      const inputElement = cmtElement.querySelector('input')
      const id = cmtElement.getAttribute('data-id')
      inputElement.addEventListener('blur', () => {
        if (inputElement.value.trim() === '') {
          vditor.removeCommentIds([id])
          removeComment(cmtElement, id)
        }
      })
      cmtElement.querySelector('button').addEventListener('click', () => {
        vditor.removeCommentIds([id])
        removeComment(cmtElement, id)
      })

      cmtElement.addEventListener('mouseover', () => {
        vditor.hlCommentIds([id])
      })

      cmtElement.addEventListener('mouseout', () => {
        vditor.unHlCommentIds([id])
      })
    }

    const removeComment = (cmtElement, id) => {
      cmtElement.remove()

      let cmts = localStorage.getItem('cmts')
      if (!cmts) {
        return
      } else {
        cmts = JSON.parse(cmts)
      }
      cmts.find((item, index) => {
        if (item.id === id) {
          cmts.splice(index, 1)
          return true
        }
      })
      localStorage.setItem('cmts', JSON.stringify(cmts))
    }

    const renderComments = (ids) => {
      let cmts = localStorage.getItem('cmts')
      if (!cmts) {
        localStorage.setItem('cmts', '[]')
        cmts = []
      } else {
        cmts = JSON.parse(cmts)
      }

      ids.forEach(commentData => {
        let text = ''
        cmts.find((item) => {
          if (item.id === commentData.id) {
            text = item.text
            return true
          }
        })

        const cmtElement = document.createElement('div')
        cmtElement.setAttribute('data-id', commentData.id)
        cmtElement.setAttribute('style', `top:${commentData.top}px`)
        cmtElement.innerHTML = `<div>
${text}
<div class="fn-flex">
    <input class="vcomment__input"><button>删除</button>
</div>
</div>`
        cmtElement.value = text
        document.getElementById('comments').
          insertAdjacentElement('beforeend', cmtElement)
        // 高度调整
        const previousElement = cmtElement.previousElementSibling
        if (previousElement) {
          const previousTop = parseInt(previousElement.style.top) +
            previousElement.clientHeight + 20
          if (previousTop > commentData.top) {
            cmtElement.style.top = previousTop + 'px'
          }
        }
        bindCommentEvent(cmtElement)
      })

      document.getElementById('comments').addEventListener("scroll", () => {
        vditor.vditor.wysiwyg.element.scrollTop = document.getElementById('comments').scrollTop
      })
    }

    const matchCommentsTop = (commentsData) => {
      commentsData.forEach((item) => {
        const commentElement = document.querySelector(
          `#comments div[data-id="${item.id}"]`)
        commentElement.setAttribute('style', `top:${item.top}px`)
        // 高度调整
        const previousElement = commentElement.previousElementSibling
        if (previousElement) {
          const previousTop = parseInt(previousElement.style.top) +
            previousElement.clientHeight + 20
          if (previousTop > item.top) {
            commentElement.style.top = previousTop + 'px'
          }
        }
      })

      document.getElementById('comments').scrollTop = vditor.vditor.wysiwyg.element.scrollTop
    }

    vditor = new Vditor('vditor', {
      cdn: "https://cdn.jsdelivr.net/npm/vditor",
      hint: {emojiPath: "https://cdn.jsdelivr.net/npm/vditor/dist/images/emoji"},
      preview: {theme: {path: "https://cdn.jsdelivr.net/npm/vditor/dist/css/content-theme"}},
      mode: 'wysiwyg',
      height: 360,
      value: '选中文字后即可进行评论',
      comment: {
        enable: true,
        adjustTop(commentsData) {
          matchCommentsTop(commentsData)
        },
        add (id, text, commentsData) {
          commentsData.find((item, index) => {
            if (item.id === id) {
              const cmtElement = document.createElement('div')
              cmtElement.setAttribute('data-id', id)
              cmtElement.innerHTML = `<div>
${text}
<div class="fn-flex">
    <input class="vcomment__input"><button>删除</button>
</div>
</div>`
              cmtElement.value = text
              if (index === 0) {
                document.querySelector('#comments').
                  insertAdjacentElement('beforeend', cmtElement)
              } else {
                document.querySelector(
                  `#comments div[data-id="${commentsData[index - 1].id}"]`).
                  insertAdjacentElement('afterend', cmtElement)
              }
              bindCommentEvent(cmtElement)
              cmtElement.querySelector('input').focus()
              let cmts = localStorage.getItem('cmts')
              if (!cmts) {
                localStorage.setItem('cmts', '[]')
                cmts = []
              } else {
                cmts = JSON.parse(cmts)
              }
              cmts.push({id, text})
              localStorage.setItem('cmts', JSON.stringify(cmts))
              return true
            }
          })
          matchCommentsTop(commentsData)
        },
        remove (ids) {
          ids.forEach((id) => {
            removeComment(document.querySelector(`#comments div[data-id="${id}"]`),
              id)
          })
          matchCommentsTop(vditor.getCommentIds())
        },
        scroll (top) {
          document.getElementById('comments').scrollTop = top
        },
      },
      after () {
        renderComments(vditor.getCommentIds())
      },
    })
  }
</script>
</body>
</html>
